﻿
using ControlzEx.Standard;
using DryIoc;
using Modbus.Device;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;

namespace ModbusMaster
{
    public class CommuMaster
    {
        private string ip = "127.0.0.1";
        private int port = 502;

        DateTime dtDisconnect = new DateTime();
        DateTime dtNow = new DateTime();
        bool NetworkIsOk = false;
        TcpClient tcpClient;
        ModbusIpMaster master = null;
        public bool Connected
        {
            get
            {
                return NetworkIsOk;
            }
        }
        public CommuMaster(string IP, int Port)
        {
            ip = IP;
            port = Port;
            NetworkIsOk = Connect();
        }
        #region 公用方法
        public int ReadHoldingRegistersToInt(byte slaveAddress, ushort startAddress)
        {
            try
            {
                ushort[] value = ReadHoldingRegisters(slaveAddress, startAddress, 2);
                return UShortArrayToIntWithByteSwap(value);
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message);
            }
        }
        public ushort ReadHoldingRegistersToBool(byte slaveAddress, ushort startAddress)
        {
            try
            {
                ushort[] value = ReadHoldingRegisters(slaveAddress, startAddress, 1);
                return value[0];
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message);
            }
        }
        public short ReadHoldingRegistersToShort(byte slaveAddress, ushort startAddress)
        {
            try
            {
                ushort[] value = ReadHoldingRegisters(slaveAddress, startAddress, 1);
                return ShortArrayToShortWithByteSwap(value);
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message);
            }
        }
        public ushort ReadHoldingRegistersToUshort(byte slaveAddress, ushort startAddress)
        {
            try
            {
                ushort[] value = ReadHoldingRegisters(slaveAddress, startAddress, 1);
                return UShortArrayToUShortWithByteSwap(value);
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message);
            }
        }
        public uint ReadHoldingRegistersToUint(byte slaveAddress, ushort startAddress)
        {
            try
            {
                ushort[] value = ReadHoldingRegisters(slaveAddress, startAddress, 2);
                return UShortArrayToUintWithByteSwap(value);
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message);
            }
        }
        public float ReadHoldingRegistersToFloat(byte slaveAddress, ushort startAddress)
        {
            try
            {
                ushort[] value = ReadHoldingRegisters(slaveAddress, startAddress, 2);
                return UShortArrayToFloatWithByteSwap(value);
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message);
            }
        }
        public double ReadHoldingRegistersToDouble(byte slaveAddress, ushort startAddress)
        {
            try
            {
                ushort[] value = ReadHoldingRegisters(slaveAddress, startAddress, 4);
                return UShortArrayToDoubleWithByteSwap(value);
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message);
            }
        }
        public string ReadHoldingRegistersToString(byte slaveAddress, ushort startAddress, ushort num)
        {
            try
            {
                ushort[] value = ReadHoldingRegisters(slaveAddress, startAddress, num);
                return UShortArrayToStringWithByteSwap(value);
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message);
            }
        }
        public void WriteHoldingRegisterFromInt(byte slaveAddress, ushort startAddress, int value)
        {
            WriteMultipleRegisters(slaveAddress, startAddress, IntToUShortArrayWithByteSwap(value));
        }
        public void WriteHoldingRegisterFromUint(byte slaveAddress, ushort startAddress, uint value)
        {
            WriteMultipleRegisters(slaveAddress, startAddress, UintToUShortArrayWithByteSwap(value));
        }
        public void WriteHoldingRegisterFromUshort(byte slaveAddress, ushort startAddress, ushort value)
        {
            WriteMultipleRegisters(slaveAddress, startAddress, UShortToUShortArrayWithByteSwap(value));
        }
        public void WriteHoldingRegisterFromshort(byte slaveAddress, ushort startAddress, short value)
        {
            WriteMultipleRegisters(slaveAddress, startAddress, ShortToUShortArrayWithByteSwap(value));
        }
        public void WriteHoldingRegisterFromFloat(byte slaveAddress, ushort startAddress, float value)
        {
            WriteMultipleRegisters(slaveAddress, startAddress, FloatToUShortArrayWithByteSwap(value));
        }
        public void WriteHoldingRegisterFromDouble(byte slaveAddress, ushort startAddress, double value)
        {
            WriteMultipleRegisters(slaveAddress, startAddress, DoubleToUShortArrayWithByteSwap(value));
        }
        public void WriteHoldingRegisterFromString(byte slaveAddress, ushort startAddress, string value)
        {
            WriteMultipleRegisters(slaveAddress, startAddress, StringToUShortArrayWithByteSwap(value));
        }
        public void WriteHoldingRegisterFromBool(byte slaveAddress, ushort startAddress, bool value)
        {
            WriteSingleRegister(slaveAddress, startAddress, value ? (ushort)1 : (ushort)0);
        }
        public bool ReadCoil(byte slaveAddress, ushort startAddress, ushort num)
        {
            bool[] value = ReadCoils(slaveAddress, startAddress, num);
            return value[0];
        }
        public void WriteCoils(byte slaveAddress, ushort startAddress, bool[] value)
        {
            WriteMultipleCoils(slaveAddress, startAddress, value);
        }
        public bool[] ReadMutilCoils(byte slaveAddress, ushort startAddress, ushort num)
        {
            bool[] value = ReadCoils(slaveAddress, startAddress, num);
            return value;
        }
        public int ReadInputRegistersToInt(byte slaveAddress, ushort startAddress)
        {
            ushort[] value = ReadInputRegisters(slaveAddress, startAddress, 2);
            return UShortArrayToIntWithByteSwap(value);
        }
        public bool ReadInputRegistersToBool(byte slaveAddress, ushort startAddress)
        {
            ushort[] value = ReadInputRegisters(slaveAddress, startAddress, 1);
            return value[0] == 1;
        }
        public short ReadInputRegistersToShort(byte slaveAddress, ushort startAddress)
        {
            ushort[] value = ReadInputRegisters(slaveAddress, startAddress, 1);
            return ShortArrayToShortWithByteSwap(value);
        }
        public ushort ReadInputRegistersToUshort(byte slaveAddress, ushort startAddress)
        {
            ushort[] value = ReadInputRegisters(slaveAddress, startAddress, 1);
            return UShortArrayToUShortWithByteSwap(value);
        }
        public uint ReadInputRegistersToUint(byte slaveAddress, ushort startAddress)
        {
            ushort[] value = ReadInputRegisters(slaveAddress, startAddress, 2);
            return UShortArrayToUintWithByteSwap(value);
        }
        public float ReadInputRegistersToFloat(byte slaveAddress, ushort startAddress)
        {
            ushort[] value = ReadInputRegisters(slaveAddress, startAddress, 2);
            return UShortArrayToFloatWithByteSwap(value);
        }
        public double ReadInputRegistersToDouble(byte slaveAddress, ushort startAddress)
        {
            ushort[] value = ReadInputRegisters(slaveAddress, startAddress, 4);
            return UShortArrayToDoubleWithByteSwap(value);
        }
        public string ReadInputRegistersToString(byte slaveAddress, ushort startAddress, ushort num)
        {
            ushort[] value = ReadInputRegisters(slaveAddress, startAddress, num);
            return UShortArrayToStringWithByteSwap(value);
        }
        #endregion
        private bool Connect()
        {
            if (master != null)
                master.Dispose();
            if (tcpClient != null)
                tcpClient.Close();
            if (CheckInternet())
            {
                try
                {
                    tcpClient = new TcpClient();
                    IAsyncResult asyncResult = tcpClient.BeginConnect(ip, port, null, null);
                    asyncResult.AsyncWaitHandle.WaitOne(1000, true); //wait for 3 sec 
                    if (!asyncResult.IsCompleted)
                    {
                        tcpClient.Close();
                        Console.WriteLine(DateTime.Now.ToString() + ":Cannot connect to server.");
                        return false;
                    }
                    // create Modbus TCP Master by the tcpclient 
                    master = ModbusIpMaster.CreateIp(tcpClient);
                    master.Transport.Retries = 0;   //don't have to do retries 
                    master.Transport.ReadTimeout = 200;
                    master.Transport.WriteTimeout = 200;
                    Console.WriteLine(DateTime.Now.ToString() + ":Connect to server.");
                    return true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(DateTime.Now.ToString() + ":Connect process " + ex.StackTrace +
                "==>" + ex.Message);
                    return false;
                }
            }
            return false;

        }
        private ushort[] ReadHoldingRegisters(byte slaveAddress, ushort startAddress, ushort num)
        {
            ushort[] value = null;
            //start timer1, timer1.Interval = 1000 ms 
            try
            {
                if (NetworkIsOk)
                {
                    #region Master to Slave 
                    value = master.ReadHoldingRegisters(slaveAddress, startAddress, num);
                    return value;
                    #endregion
                }
                else
                {
                    //retry connecting 
                    dtNow = DateTime.Now;
                    if ((dtNow - dtDisconnect) > TimeSpan.FromSeconds(10))
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Start connecting");
                        NetworkIsOk = Connect();
                        if (!NetworkIsOk)
                        {
                            Console.WriteLine(DateTime.Now.ToString() + ":Connecting fail. Wait for retry");
                            dtDisconnect = DateTime.Now;
                        }
                    }
                    else
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Wait for retry connecting");
                    }
                    return value;
                }
            }
            catch (Exception ex)
            {
                if (ex.Source.Equals("System"))
                {
                    //set NetworkIsOk to false and retry connecting 
                    NetworkIsOk = false;
                    Console.WriteLine(ex.Message);
                    dtDisconnect = DateTime.Now;
                }
                return value;
            }
        }
        public void WriteSingleRegister(byte slaveAddress, ushort startAddress, ushort value)
        {
            //start timer1, timer1.Interval = 1000 ms 
            try
            {
                if (NetworkIsOk)
                {
                    #region Master to Slave 
                    master.WriteSingleRegister(slaveAddress, startAddress, value);
                    #endregion
                }
                else
                {
                    //retry connecting 
                    dtNow = DateTime.Now;
                    if ((dtNow - dtDisconnect) > TimeSpan.FromSeconds(10))
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Start connecting");
                        NetworkIsOk = Connect();
                        if (!NetworkIsOk)
                        {
                            Console.WriteLine(DateTime.Now.ToString() + ":Connecting fail. Wait for retry");
                            dtDisconnect = DateTime.Now;
                        }
                    }
                    else
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Wait for retry connecting");
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex.Source.Equals("System"))
                {
                    //set NetworkIsOk to false and retry connecting 
                    //NetworkIsOk = false;
                    //Console.WriteLine(ex.Message);
                    //dtDisconnect = DateTime.Now;
                }
            }
        }
        private void WriteMultipleRegisters(byte slaveAddress, ushort startAddress, ushort[] value)
        {
            //start timer1, timer1.Interval = 1000 ms 
            try
            {
                if (NetworkIsOk)
                {
                    #region Master to Slave 
                    master.WriteMultipleRegisters(slaveAddress, startAddress, value);
                    #endregion
                }
                else
                {
                    //retry connecting 
                    dtNow = DateTime.Now;
                    if ((dtNow - dtDisconnect) > TimeSpan.FromSeconds(10))
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Start connecting");
                        NetworkIsOk = Connect();
                        if (!NetworkIsOk)
                        {
                            Console.WriteLine(DateTime.Now.ToString() + ":Connecting fail. Wait for retry");
                            dtDisconnect = DateTime.Now;
                        }
                    }
                    else
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Wait for retry connecting");
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex.Source.Equals("System"))
                {
                    //set NetworkIsOk to false and retry connecting 
                    //NetworkIsOk = false;
                    //Console.WriteLine(ex.Message);
                    //dtDisconnect = DateTime.Now;
                }
            }
        }
        private bool[] ReadCoils(byte slaveAddress, ushort startAddress, ushort num)
        {
            bool[] value = null;
            //start timer1, timer1.Interval = 1000 ms 
            try
            {
                if (NetworkIsOk)
                {
                    #region Master to Slave 
                    //read AI, AO, DI, DO 
                    value = master.ReadCoils(slaveAddress, startAddress, num);
                    return value;
                    #endregion
                }
                else
                {
                    //retry connecting 
                    dtNow = DateTime.Now;
                    if ((dtNow - dtDisconnect) > TimeSpan.FromSeconds(10))
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Start connecting");
                        NetworkIsOk = Connect();
                        if (!NetworkIsOk)
                        {
                            Console.WriteLine(DateTime.Now.ToString() + ":Connecting fail. Wait for retry");
                            dtDisconnect = DateTime.Now;
                        }
                    }
                    else
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Wait for retry connecting");
                    }
                    return value;
                }
            }
            catch (Exception ex)
            {
                if (ex.Source.Equals("System"))
                {
                    //set NetworkIsOk to false and retry connecting 
                    NetworkIsOk = false;
                    Console.WriteLine(ex.Message);
                    dtDisconnect = DateTime.Now;
                }
                return value;
            }
        }
        private void WriteSingleCoil(byte slaveAddress, ushort startAddress, bool value)
        {
            //start timer1, timer1.Interval = 1000 ms 
            try
            {
                if (NetworkIsOk)
                {
                    #region Master to Slave 
                    //read AI, AO, DI, DO 
                    master.WriteSingleCoil(slaveAddress, startAddress, value);
                    #endregion
                }
                else
                {
                    //retry connecting 
                    dtNow = DateTime.Now;
                    if ((dtNow - dtDisconnect) > TimeSpan.FromSeconds(10))
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Start connecting");
                        NetworkIsOk = Connect();
                        if (!NetworkIsOk)
                        {
                            Console.WriteLine(DateTime.Now.ToString() + ":Connecting fail. Wait for retry");
                            dtDisconnect = DateTime.Now;
                        }
                    }
                    else
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Wait for retry connecting");
                    }
                }
            }
            catch (Exception ex)
            {
                //if (ex.Source.Equals("System"))
                //{
                //    //set NetworkIsOk to false and retry connecting 
                //    NetworkIsOk = false;
                //    Console.WriteLine(ex.Message);
                //    dtDisconnect = DateTime.Now;
                //}
            }
        }
        private void WriteMultipleCoils(byte slaveAddress, ushort startAddress, bool[] value)
        {
            //start timer1, timer1.Interval = 1000 ms 
            try
            {
                if (NetworkIsOk)
                {
                    #region Master to Slave 
                    //read AI, AO, DI, DO 
                    master.WriteMultipleCoils(slaveAddress, startAddress, value);
                    #endregion
                }
                else
                {
                    //retry connecting 
                    dtNow = DateTime.Now;
                    if ((dtNow - dtDisconnect) > TimeSpan.FromSeconds(10))
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Start connecting");
                        NetworkIsOk = Connect();
                        if (!NetworkIsOk)
                        {
                            Console.WriteLine(DateTime.Now.ToString() + ":Connecting fail. Wait for retry");
                            dtDisconnect = DateTime.Now;
                        }
                    }
                    else
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Wait for retry connecting");
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex.Source.Equals("System"))
                {
                    //set NetworkIsOk to false and retry connecting 
                    //NetworkIsOk = false;
                    //Console.WriteLine(ex.Message);
                    //dtDisconnect = DateTime.Now;
                }
            }
        }
        private ushort[] ReadInputRegisters(byte slaveAddress, ushort startAddress, ushort num)
        {
            ushort[] value = null;
            //start timer1, timer1.Interval = 1000 ms 
            try
            {
                if (NetworkIsOk)
                {
                    #region Master to Slave 
                    //read AI, AO, DI, DO 
                    value = master.ReadInputRegisters(slaveAddress, startAddress, num);
                    return value;
                    #endregion
                }
                else
                {
                    //retry connecting 
                    dtNow = DateTime.Now;
                    if ((dtNow - dtDisconnect) > TimeSpan.FromSeconds(10))
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Start connecting");
                        NetworkIsOk = Connect();
                        if (!NetworkIsOk)
                        {
                            Console.WriteLine(DateTime.Now.ToString() + ":Connecting fail. Wait for retry");
                            dtDisconnect = DateTime.Now;
                        }
                    }
                    else
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Wait for retry connecting");
                    }
                    return value;
                }
            }
            catch (Exception ex)
            {
                if (ex.Source.Equals("System"))
                {
                    //set NetworkIsOk to false and retry connecting 
                    NetworkIsOk = false;
                    Console.WriteLine(ex.Message);
                    dtDisconnect = DateTime.Now;
                }
                return value;
            }
        }
        private bool[] ReadInputs(byte slaveAddress, ushort startAddress, ushort num)
        {
            bool[] value = null;
            //start timer1, timer1.Interval = 1000 ms 
            try
            {
                if (NetworkIsOk)
                {
                    #region Master to Slave 
                    //read AI, AO, DI, DO 
                    value = master.ReadInputs(slaveAddress, startAddress, num);
                    return value;
                    #endregion
                }
                else
                {
                    //retry connecting 
                    dtNow = DateTime.Now;
                    if ((dtNow - dtDisconnect) > TimeSpan.FromSeconds(100))
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Start connecting");
                        NetworkIsOk = Connect();
                        if (!NetworkIsOk)
                        {
                            Console.WriteLine(DateTime.Now.ToString() + ":Connecting fail. Wait for retry");
                            dtDisconnect = DateTime.Now;
                        }
                    }
                    else
                    {
                        Console.WriteLine(DateTime.Now.ToString() + ":Wait for retry connecting");
                    }
                    return value;
                }
            }
            catch (Exception ex)
            {
                if (ex.Source.Equals("System"))
                {
                    //set NetworkIsOk to false and retry connecting 
                    NetworkIsOk = false;
                    Console.WriteLine(ex.Message);
                    dtDisconnect = DateTime.Now;
                }
                return value;
            }
        }

        #region 类型转换
        // 将 ushort[] 转换为 int
        private static int ushorts2int(ushort[] res)
        {
            int high = res[0];
            int low = res[1];
            int value = (high << 16) + low;
            return value;
        }
        // 将 int 转换为 ushort[]
        private static ushort[] int2ushorts(int res)
        {
            ushort ust1 = (ushort)(res >> 16);
            ushort ust2 = (ushort)res;
            return new ushort[] { ust1, ust2 };
        }
        // int 转 ushort[] 并高低位互换 CD-AB模式
        private static ushort[] IntToUShortArrayWithByteSwap(int input)
        {
            // 先将 int 转换为字节数组
            byte[] intBytes = BitConverter.GetBytes(input);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(intBytes);
            }

            ushort[] ushortArray = new ushort[2];
            // 把字节数组转换为 ushort 数组
            ushortArray[0] = (ushort)((intBytes[0] << 8) | intBytes[1]);
            ushortArray[1] = (ushort)((intBytes[2] << 8) | intBytes[3]);

            // 进行 CD - AB 切换
            ushort temp = ushortArray[0];
            ushortArray[0] = ushortArray[1];
            ushortArray[1] = temp;

            return ushortArray;
        }
        // ushort[] 转 int 并高低位互换 CD-AB模式
        private static int UShortArrayToIntWithByteSwap(ushort[] input)
        {
            if (input.Length != 2)
            {
                throw new ArgumentException("输入的 ushort 数组长度必须为 2。");
            }

            // 进行 CD - AB 切换
            ushort temp = input[0];
            input[0] = input[1];
            input[1] = temp;

            byte[] byteArray = new byte[4];
            byteArray[0] = (byte)(input[0] >> 8);
            byteArray[1] = (byte)(input[0] & 0xFF);
            byteArray[2] = (byte)(input[1] >> 8);
            byteArray[3] = (byte)(input[1] & 0xFF);

            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(byteArray);
            }

            return BitConverter.ToInt32(byteArray, 0);
        }
        // 将 ushort[] 转换为 float
        private static float UshortArrayToFloat(ushort[] ushortArray)
        {
            if (ushortArray.Length != 2)
            {
                throw new ArgumentException("ushort 数组的长度必须为 2。");
            }
            byte[] bytes = new byte[4];
            Buffer.BlockCopy(ushortArray, 0, bytes, 0, 4);
            return BitConverter.ToSingle(bytes, 0);
        }
        // 将 float 转换为 ushort[]
        private static ushort[] FloatToUshortArray(float value)
        {
            byte[] bytes = BitConverter.GetBytes(value);
            ushort[] ushortArray = new ushort[2];
            Buffer.BlockCopy(bytes, 0, ushortArray, 0, 4);
            return ushortArray;
        }
        // float 转 ushort[] 并高低位互换 CD-AB模式
        private static ushort[] FloatToUShortArrayWithByteSwap(float input)
        {
            // 将 float 转换为字节数组
            byte[] floatBytes = BitConverter.GetBytes(input);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(floatBytes);
            }

            ushort[] ushortArray = new ushort[2];
            // 把字节数组转换为 ushort 数组
            ushortArray[0] = (ushort)((floatBytes[0] << 8) | floatBytes[1]);
            ushortArray[1] = (ushort)((floatBytes[2] << 8) | floatBytes[3]);

            // 进行 CD - AB 切换
            ushort temp = ushortArray[0];
            ushortArray[0] = ushortArray[1];
            ushortArray[1] = temp;

            return ushortArray;
        }
        // ushort[] 转 float 并高低位互换 CD-AB模式
        private static float UShortArrayToFloatWithByteSwap(ushort[] input)
        {
            if (input.Length != 2)
            {
                throw new ArgumentException("输入的 ushort 数组长度必须为 2。");
            }

            // 进行 CD - AB 切换
            ushort temp = input[0];
            input[0] = input[1];
            input[1] = temp;

            byte[] byteArray = new byte[4];
            byteArray[0] = (byte)(input[0] >> 8);
            byteArray[1] = (byte)(input[0] & 0xFF);
            byteArray[2] = (byte)(input[1] >> 8);
            byteArray[3] = (byte)(input[1] & 0xFF);

            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(byteArray);
            }

            return BitConverter.ToSingle(byteArray, 0);
        }
        // 将 ushort[] 转换为 double
        private static double UshortArrayToDouble(ushort[] ushortArray)
        {
            if (ushortArray.Length != 4)
            {
                throw new ArgumentException("ushort 数组的长度必须为 4。");
            }
            byte[] bytes = new byte[8];
            Buffer.BlockCopy(ushortArray, 0, bytes, 0, 8);
            return BitConverter.ToDouble(bytes, 0);
        }
        // 将 double 转换为 ushort[]
        private static ushort[] DoubleToUshortArray(double value)
        {
            byte[] bytes = BitConverter.GetBytes(value);
            ushort[] ushortArray = new ushort[4];
            Buffer.BlockCopy(bytes, 0, ushortArray, 0, 8);
            return ushortArray;
        }
        // double 转 ushort[] 并高低位互换 CD-AB模式
        static ushort[] DoubleToUShortArrayWithByteSwap(double input)
        {
            // 将 double 转换为字节数组
            byte[] doubleBytes = BitConverter.GetBytes(input);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(doubleBytes);
            }

            ushort[] ushortArray = new ushort[4];
            for (int i = 0; i < 4; i++)
            {
                ushortArray[i] = (ushort)((doubleBytes[i * 2] << 8) | doubleBytes[i * 2 + 1]);
            }

            // 进行 GH - EF - CD - AB 切换
            ushort[] swappedArray = new ushort[4];
            swappedArray[0] = ushortArray[3];
            swappedArray[1] = ushortArray[2];
            swappedArray[2] = ushortArray[1];
            swappedArray[3] = ushortArray[0];

            return swappedArray;
        }
        // ushort[] 转 double 并高低位互换 CD-AB模式
        static double UShortArrayToDoubleWithByteSwap(ushort[] input)
        {
            if (input.Length != 4)
            {
                throw new ArgumentException("输入的 ushort 数组长度必须为 4。");
            }

            // 进行 GH - EF - CD - AB 切换
            ushort[] swappedArray = new ushort[4];
            swappedArray[0] = input[3];
            swappedArray[1] = input[2];
            swappedArray[2] = input[1];
            swappedArray[3] = input[0];

            byte[] byteArray = new byte[8];
            for (int i = 0; i < 4; i++)
            {
                byteArray[i * 2] = (byte)(swappedArray[i] >> 8);
                byteArray[i * 2 + 1] = (byte)(swappedArray[i] & 0xFF);
            }

            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(byteArray);
            }

            return BitConverter.ToDouble(byteArray, 0);
        }
        // 将 string 转换为 ushort[]
        private static ushort[] StringToUshortArray(string str)
        {
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(str);
            ushort[] ushortArray = new ushort[bytes.Length / 2];
            Buffer.BlockCopy(bytes, 0, ushortArray, 0, bytes.Length);
            return ushortArray;
        }
        // 将 ushort[] 转换为 string
        private static string UshortArrayToString(ushort[] ushortArray)
        {
            byte[] bytes = new byte[ushortArray.Length * 2];
            Buffer.BlockCopy(ushortArray, 0, bytes, 0, bytes.Length);
            return System.Text.Encoding.UTF8.GetString(bytes);
        }
        // string 转 ushort[] 并高低位互换 CD-AB模式
        private static ushort[] StringToUShortArrayWithByteSwap(string value)
        {
            if (value == null)
            {
                return null;
            }

            List<ushort> list = new List<ushort>();
            byte[] bytes = Encoding.UTF8.GetBytes(value);
            List<byte> list2 = new List<byte>();
            list2.AddRange(bytes);
            if (bytes.Length % 2 != 0)
            {
                list2.Add(0);
            }

            byte[] value2 = list2.ToArray();
            for (int i = 0; i < list2.Count; i += 2)
            {
                list.Add(BitConverter.ToUInt16(value2, i));
            }

            return list.ToArray();
        }
        // ushort[] 转 string 并高低位互换 CD-AB模式
        private static string UShortArrayToStringWithByteSwap(ushort[] input)
        {
            List<byte> list = new List<byte>();
            for (int i = 0; i < input.Length; i++)
            {
                byte[] bytes = BitConverter.GetBytes(input[i]);
                list.AddRange(bytes);
            }
            return Encoding.UTF8.GetString(list.ToArray()); ;
        }
        // 将 uint 转换为 ushort[]
        private static ushort[] UintToUshortArray(uint value)
        {
            ushort[] ushortArray = new ushort[2];
            ushortArray[0] = (ushort)(value & 0xFFFF);
            ushortArray[1] = (ushort)(value >> 16);
            return ushortArray;
        }
        // 将 ushort[] 转换为 uint
        private static uint UshortArrayToUint(ushort[] ushortArray)
        {
            if (ushortArray.Length != 2)
            {
                throw new ArgumentException("输入的 ushort 数组长度必须为 2。");
            }
            uint result = (uint)(ushortArray[1] << 16) | ushortArray[0];
            return result;
        }
        // uint 转 ushort[] 并高低位互换 CD-AB模式
        private static ushort[] UintToUShortArrayWithByteSwap(uint input)
        {
            // 将 uint 转换为字节数组
            byte[] uintBytes = BitConverter.GetBytes(input);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(uintBytes);
            }

            ushort[] ushortArray = new ushort[2];
            // 把字节数组转换为 ushort 数组
            ushortArray[0] = (ushort)((uintBytes[0] << 8) | uintBytes[1]);
            ushortArray[1] = (ushort)((uintBytes[2] << 8) | uintBytes[3]);

            // 进行 CD - AB 切换
            ushort temp = ushortArray[0];
            ushortArray[0] = ushortArray[1];
            ushortArray[1] = temp;

            return ushortArray;
        }
        // ushort[] 转 uint 并高低位互换 CD-AB模式
        private static uint UShortArrayToUintWithByteSwap(ushort[] input)
        {
            if (input.Length != 2)
            {
                throw new ArgumentException("输入的 ushort 数组长度必须为 2。");
            }

            // 进行 CD - AB 切换
            ushort temp = input[0];
            input[0] = input[1];
            input[1] = temp;

            byte[] byteArray = new byte[4];
            byteArray[0] = (byte)(input[0] >> 8);
            byteArray[1] = (byte)(input[0] & 0xFF);
            byteArray[2] = (byte)(input[1] >> 8);
            byteArray[3] = (byte)(input[1] & 0xFF);

            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(byteArray);
            }

            return BitConverter.ToUInt32(byteArray, 0);
        }
        // ushort 转 ushort[] 并高低位互换 CD-AB模式
        private static ushort[] UShortToUShortArrayWithByteSwap(ushort input)
        {
            return new ushort[] { input };
        }
        // ushort[] 转 ushort 并高低位互换 CD-AB模式
        private static ushort UShortArrayToUShortWithByteSwap(ushort[] input)
        {
            if (input.Length != 1)
            {
                throw new ArgumentException("输入的 ushort 数组长度必须为 1。");
            }

            return input[0];
        }
        // 将 ushort[] 转换为 short
        private static short UshortArrayToShort(ushort[] ushortArray)
        {
            if (ushortArray == null || ushortArray.Length == 0)
            {
                throw new ArgumentException("输入的 ushort 数组不能为空。");
            }
            // 假设只取数组的前两个元素组合成一个 short
            if (ushortArray.Length < 2)
            {
                throw new ArgumentException("输入的 ushort 数组长度至少为 2。");
            }
            // 低 16 位和高 16 位组合
            return (short)((ushortArray[1] << 8) | ushortArray[0]);
        }
        // 将 short 转换为 ushort[]
        private static ushort[] ShortToUshortArray(short value)
        {
            ushort[] result = new ushort[2];
            result[0] = (ushort)(value & 0xFFFF);
            result[1] = (ushort)((value >> 8) & 0xFFFF);
            return result;
        }
        // short 转 ushort[] 并高低位互换 CD-AB模式
        static ushort[] ShortToUShortArrayWithByteSwap(short input)
        {
            ushort ushortValue = (ushort)input;
            // 这里只有一个 ushort，CD - AB 切换无实际意义，直接返回
            return new ushort[] { ushortValue };
        }
        // short[] 转 short 并高低位互换 CD-AB模式
        static short ShortArrayToShortWithByteSwap(ushort[] input)
        {
            if (input.Length != 1)
            {
                throw new ArgumentException("输入的 ushort 数组长度必须为 1。");
            }
            // 这里只有一个 ushort，CD - AB 切换无实际意义
            return (short)input[0];
        }
        #endregion

        private bool CheckInternet()
        {
            InternetConnectionState flag = InternetConnectionState.INTERNET_CONNECTION_LAN;
            return InternetGetConnectedState(ref flag, 0);
        }
        [DllImport("WININET", CharSet = CharSet.Auto)]
        static extern bool InternetGetConnectedState(ref InternetConnectionState lpdwFlags, int dwReserved);
        enum InternetConnectionState : int
        {
            INTERNET_CONNECTION_MODEM = 0x1,
            INTERNET_CONNECTION_LAN = 0x2,
            INTERNET_CONNECTION_PROXY = 0x4,
            INTERNET_RAS_INSTALLED = 0x10,
            INTERNET_CONNECTION_OFFLINE = 0x20,
            INTERNET_CONNECTION_CONFIGURED = 0x40
        }
    }
}
